package io.bd;

import io.Archivo;
import io.Carpeta;
import io.Cliente;
import io.Expediente;
import java.io.BufferedReader;
import java.io.IOException;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

/**
 *
 * @author Mariano Zapata
 */
public class ABMRCarpeta {
    
    private Connection conexion;
    
    public ABMRCarpeta(Connection conexion) {
        this.conexion= conexion;
    }
    
    public void recuperar(Carpeta carpeta, ABMRCliente auxiliarCliente, ABMRArchivo auxiliarArchivo) throws SQLException
    {
        String renglon= "SELECT id, nombre FROM Directorio WHERE es_expediente= false AND padre= "
                + carpeta.obtenerId() + " ORDER BY nombre";
        List<Carpeta> hijos= new ArrayList<Carpeta>();
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        while (r.next())
        {
            List<Long> ruta= carpeta.obtenerCopiaRuta();
            ruta.add(r.getLong(1));
            Carpeta c= new Carpeta(ruta);
            c.setNombre(r.getString(2));
            c.setEsExpediente(false);
            if (this.poseeCarpetas(c) || auxiliarCliente.poseeClientes(c) || auxiliarArchivo.poseeArchivos(c))
                c.setPoseeHijos(true);
            else
                c.setPoseeHijos(false);
            hijos.add(c);
        }
        renglon= "SELECT id, nombre FROM Directorio WHERE es_expediente= true AND padre= " + carpeta.obtenerId() +
                " ORDER BY nombre";
        r= consulta.executeQuery(renglon);
        while (r.next())
        {
            List<Long> ruta= carpeta.obtenerCopiaRuta();
            ruta.add(r.getLong(1));
            Carpeta c= new Carpeta(ruta);
            c.setNombre(r.getString(2));
            c.setEsExpediente(true);
            if (auxiliarCliente.poseeClientes(c) || auxiliarArchivo.poseeArchivos(c))
                c.setPoseeHijos(true);
            else
                c.setPoseeHijos(false);
            hijos.add(c);
        }
        r.close();
        consulta.close();
        carpeta.setHijosCarpeta(hijos);
    }
    
    public List<Carpeta> recuperarHijosCarpeta(Carpeta carpeta) throws SQLException
    {
        ArrayList<Carpeta> ret= new ArrayList<Carpeta>();
        String renglon= "SELECT id FROM Directorio WHERE padre= " + carpeta.obtenerId();
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        while (r.next())
        {
            List<Long> ruta= carpeta.obtenerCopiaRuta();
            ruta.add(r.getLong(1));
            Carpeta car= new Carpeta(ruta);
            ret.add(car);
        }
        r.close();
        consulta.close();
        return ret;
    }
    
    public Carpeta obtenerCarpeta(List<Long> ruta) throws SQLException
    {
        long id= ruta.get(ruta.size() - 1);
        String renglon= "SELECT nombre, es_expediente FROM Directorio WHERE id= " + id;
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        r.next();
        Carpeta retorno= new Carpeta(ruta);
        retorno.setNombre(r.getString(1));
        retorno.setEsExpediente(r.getBoolean(2));
        r.close();
        consulta.close();
        return retorno;
    }
    
    public Carpeta crear(Carpeta c, Carpeta padre) throws SQLException
    {
        String renglon= "INSERT INTO Directorio (nombre, padre, es_expediente) VALUES (?, ?, ?)";
        List<Long> ruta= padre.obtenerCopiaRuta();
        PreparedStatement consulta= conexion.prepareStatement(renglon, PreparedStatement.RETURN_GENERATED_KEYS);
        consulta.setString(1, c.getNombre());
        consulta.setLong(2, padre.obtenerId());
        consulta.setBoolean(3, c.esExpediente());
        consulta.executeUpdate();
        ResultSet r= consulta.getGeneratedKeys();
        r.next();
        long id= r.getLong(1);
        ruta.add(id);
        r.close();
        consulta.close();
        Carpeta ret= new Carpeta(ruta);
        ret.setNombre(c.getNombre());
        ret.setEsExpediente(c.esExpediente());
        if (c.esExpediente())
        {
            renglon= "INSERT INTO Expediente (id, juzgado, secretaria) VALUES (?, ?, ?)";
            consulta= conexion.prepareStatement(renglon);
            consulta.setLong(1, id);
            consulta.setString(2, c.getExpediente().getJuzgado());
            consulta.setString(3, c.getExpediente().getSecretaria());
            consulta.executeUpdate();
            consulta.close();
            Expediente expRet= new Expediente();
            expRet.setJuzgado(c.getExpediente().getJuzgado());
            expRet.setSecretaria(c.getExpediente().getSecretaria());
            ret.setExpediente(expRet);
        }
        return ret;
    }
    
    public void guardar(Carpeta c) throws SQLException
    {
        String renglon= "UPDATE Directorio SET nombre= ? WHERE id= ?";
        PreparedStatement consulta= conexion.prepareStatement(renglon);
        consulta.setString(1, c.getNombre());
        consulta.setLong(2, c.obtenerId());
        consulta.executeUpdate();
        consulta.close();
        if (c.esExpediente())
        {
            renglon= "UPDATE Expediente SET instancia1= ?, instancia2= ?, instancia3= ?, instancia4= ?, juzgado= ?, " +
                    "secretaria= ?, iniciado= ?, terminado= ?, tipo= ?, juez= ?, secretario= ?, estado= ?, " +
                    "seguimiento= ? WHERE id= ?";
            consulta= conexion.prepareStatement(renglon);
            consulta.setString(1, c.getExpediente().getInstancia1());
            consulta.setString(2, c.getExpediente().getInstancia2());
            consulta.setString(3, c.getExpediente().getInstancia3());
            consulta.setString(4, c.getExpediente().getInstancia4());
            consulta.setString(5, c.getExpediente().getJuzgado());
            consulta.setString(6, c.getExpediente().getSecretaria());
            consulta.setDate(7, this.transformarFecha(c.getExpediente().getIniciado()));
            consulta.setDate(8, this.transformarFecha(c.getExpediente().getTerminado()));
            consulta.setString(9, c.getExpediente().getTipo());
            consulta.setString(10, c.getExpediente().getJuez());
            consulta.setString(11, c.getExpediente().getSecretario());
            consulta.setByte(12, c.getExpediente().getEstado());
            consulta.setString(13, c.getExpediente().getSeguimiento());
            consulta.setLong(14, c.obtenerId());
            consulta.executeUpdate();
            consulta.close();
        }
    }
    
    public void eliminar(Carpeta c, ABMRCliente auxiliarCliente, ABMRArchivo auxiliarArchivo) throws SQLException
    {
        String renglon= "DELETE FROM Directorio WHERE id= " + c.obtenerId();
        Statement consulta= conexion.createStatement();
        this.recuperar(c, auxiliarCliente, auxiliarArchivo);
        List<Carpeta> hijos= c.getHijosCarpeta();
        for (Carpeta p : hijos)
            this.eliminar(p, auxiliarCliente, auxiliarArchivo);
        consulta.executeUpdate(renglon);
        consulta.close();
    }
    
    public void cortar(Carpeta c, Carpeta nuevoPadre) throws SQLException
    {
        String renglon= "UPDATE Directorio SET padre= " + nuevoPadre.obtenerId() + " WHERE id= " + c.obtenerId();
        Statement consulta= conexion.createStatement();
        consulta.executeUpdate(renglon);
        consulta.close();
    }
    
    public void copiar(Carpeta c, Carpeta nuevoPadre, ABMRCliente auxiliarCliente, ABMRArchivo auxiliarArchivo)
            throws SQLException, IOException
    {
        Carpeta nueva= this.crear(c, nuevoPadre);
        this.recuperar(c, auxiliarCliente, auxiliarArchivo);
        List<Carpeta> hijosCarpetas= c.getHijosCarpeta();
        for (Carpeta p : hijosCarpetas)
            this.copiar(p, nueva, auxiliarCliente, auxiliarArchivo);
        auxiliarCliente.recuperar(c);
        List<Cliente> hijosClientes= c.getHijosCliente();
        for (Cliente i : hijosClientes)
            auxiliarCliente.copiar(i, nueva);
        auxiliarArchivo.recuperar(c);
        List<Archivo> hijosArchivos= c.getHijosArchivo();
        for (Archivo a : hijosArchivos)
            auxiliarArchivo.copiar(a, nueva);
    }
    
    public boolean existe(Carpeta c) throws SQLException
    {
        String renglon= "SELECT id FROM Directorio WHERE id= " + c.obtenerId();
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        boolean retorno= r.next();
        r.close();
        consulta.close();
        return retorno;
    }

    public void cargarExpediente(Carpeta c) throws SQLException, IOException
    {
        String renglon= "SELECT * FROM Expediente WHERE id= " + c.obtenerId();
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        r.next();
        Expediente e= new Expediente();
        e.setInstancia1(r.getString(2));
        e.setInstancia2(r.getString(3));
        e.setInstancia3(r.getString(4));
        e.setInstancia4(r.getString(5));
        e.setJuzgado(r.getString(6));
        e.setSecretaria(r.getString(7));
        e.setIniciado(this.transformarFecha(r.getDate(8)));
        e.setTerminado(this.transformarFecha(r.getDate(9)));
        e.setTipo(r.getString(10));
        e.setJuez(r.getString(11));
        e.setSecretario(r.getString(12));
        e.setEstado(r.getByte(13));
        e.setSeguimiento(this.transformarClob(r.getClob(14)));
        c.setExpediente(e);
        r.close();
        consulta.close();
    }
    
    public boolean poseeCarpetas(Carpeta c) throws SQLException
    {
        String renglon= "SELECT COUNT(id) FROM Directorio WHERE padre= " + c.obtenerId();
        Statement consulta= conexion.createStatement();
        ResultSet r= consulta.executeQuery(renglon);
        r.next();
        return (r.getLong(1) > 0);
    }

    private java.sql.Date transformarFecha(String fecha)
    {
        if (fecha.isEmpty())
            return null;
        String [] atomo= fecha.split("/");
        Calendar calendarFecha= Calendar.getInstance();
        calendarFecha.clear();
        calendarFecha.set(Integer.parseInt(atomo[2]), Integer.parseInt(atomo[1]) - 1, Integer.parseInt(atomo[0]));
        java.sql.Date sqlFecha= new java.sql.Date(calendarFecha.getTimeInMillis());
        return sqlFecha;
    }

    private String transformarFecha(java.sql.Date sqlFecha)
    {
        if (sqlFecha == null)
            return "";
        java.util.Date utilFecha= new java.util.Date(sqlFecha.getTime());
        Calendar calendarFecha= Calendar.getInstance();
        calendarFecha.setTime(utilFecha);
        String ret= this.corregirFecha(calendarFecha.get(Calendar.DATE)) + "/" +
                this.corregirFecha(calendarFecha.get(Calendar.MONTH) + 1) + "/" + calendarFecha.get(Calendar.YEAR);
        return ret;
    }

    private String corregirFecha(int valor)
    {
        if (valor < 10)
            return "0" + valor;
        else
            return String.valueOf(valor);
    }

    private String transformarClob(Clob clob) throws SQLException, IOException
    {
        StringBuilder ret= new StringBuilder();
        String aux;
        BufferedReader buffer= new BufferedReader(clob.getCharacterStream());
        while ((aux= buffer.readLine()) != null)
            ret.append(aux);
        return ret.toString();
    }
}
